package com.celesea.framework.util.tree;

import com.celesea.framework.util.CollectionKit;
import com.celesea.framework.util.Const;
import com.celesea.framework.util.StringKit;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author JackYuan
 * @create 2017-10-29 10:42
 */
public class TreeUtil {
    protected static Logger logger = LoggerFactory.getLogger(TreeUtil.class);

    public static <T extends ITree> List<String> treeChildIds(List<T> trees, String id) {
        List<String> ids = Lists.newArrayList();
        TreeUtil.treeChildIds(trees, id, ids, StringKit.isEmpty(id) ? 1 : 0);
        return ids;
    }

    private static <T extends ITree> boolean treeChildIds(List<T> lists, String id, List<String> ids, int parentMatch) {
        Iterator<T> iterator = lists.iterator();
        while (iterator.hasNext()) {
            T child = iterator.next();
            List<T> children = child.getChildren();
            if (parentMatch > 0) {
                ids.add(child.getId());
                if (CollectionKit.isNotEmpty(children)) {
                    treeChildIds(children, id, ids, parentMatch);
                }
            } else {
                boolean matchFlag = id.equals(child.getId());
                int next = parentMatch;
                if (matchFlag) {
                    // 不包含自己
                    //ids.add(child.getId());
                    next++;
                }
                if (CollectionKit.isNotEmpty(children)) {
                    treeChildIds(children, id, ids, next);
                }
            }
        }
        return false;
    }


    public static <T extends ITree> List<String> treeParentIds(List<T> trees, String id) {
        List<String> ids = Lists.newArrayList();
        if (StringKit.isNotEmpty(id)) {
            TreeUtil.treeParentIds(trees, id, ids);
        }
        return ids;
    }

    private static <T extends ITree> boolean treeParentIds(List<T> lists, String id, List<String> ids) {
        Iterator<T> iterator = lists.iterator();
        while (iterator.hasNext()) {
            T child = iterator.next();
            if (id.equals(child.getId())) {
                // 不包含自己
                // ids.add(child.getId());
                return true;
            } else {
                List<T> children = child.getChildren();
                if (CollectionKit.isNotEmpty(children)) {
                    boolean match = TreeUtil.treeParentIds(children, id, ids);
                    if (match) {
                        ids.add(child.getId());
                        return true;
                    }
                }
            }
        }
        return false;
    }

    public static <T extends ITree> List<T> build2Tree(List<T> lists, String rootId) {
        Map<String, T> maps = Maps.newHashMap();
        List<T> roots = Lists.newArrayList();
        Iterator<T> iterator = lists.iterator();
        lists.stream().forEach(root -> {
            boolean isRoot = StringKit.isEmpty(root.getParentId());
            if (isRoot || root.getId().equals(rootId)) {
                roots.add(root);
                maps.put(root.getId(), root);
            }
        });
        while (iterator.hasNext()) {
            T child = iterator.next();
            String id = child.getId();
            String parentId = child.getParentId();
            maps.put(id, child);
            boolean isRoot = StringKit.isEmpty(parentId);
            child.setLeaf(Const.Bool.TRUE);

            if (!isRoot) {
                T parent = maps.get(parentId);
                if (parent != null) {
                    List<T> children = parent.getChildren();
                    if (children == null) {
                        children = Lists.newArrayList();
                    }
                    children.add(child);
                    parent.setChildren(children);
                    parent.setLeaf(Const.Bool.FALSE);
                }
            }
        }
        return roots;
    }

    public static <T extends ITree> List<T> getNodes(List<T> roots, String parentId) {
        if (StringKit.isEmpty(parentId)) {
            return roots;
        } else {
            Iterator<T> iterator = roots.iterator();
            List<T> childrens = Lists.newArrayList();
            while (iterator.hasNext()) {
                T item = iterator.next();
                if (item.getId().equals(parentId)) {
                    childrens = item.getChildren();
                    break;
                } else {
                    childrens = TreeUtil.getNodes(item.getChildren(), parentId);
                }
            }
            return childrens;
        }
    }
}
